'''   Copyright [八月不落东方叶] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
'''


from time import sleep,time,localtime
import zipfile
from pathlib import PureWindowsPath
import os
import datetime
from threading import Thread
import sqlite3
from configparser import ConfigParser

#备份功能类exec
def crezip(dirpath, outFullName):#备份功能函数
        """
        :param dirpath: 目标文件夹路径
        :param outFullName: 压缩文件保存路径+xxxx.zip 
        """
        time1=localtime(time())
        time2="{}-{}-{}_{}点{}分{}秒".format(time1[0],time1[1],time1[2],time1[3],time1[4],time1[5])
        outFullName +='[备份]备份于' + str(time2) + '.zip'
        zip = zipfile.ZipFile(outFullName, "w", zipfile.ZIP_DEFLATED)
        for path, dirnames, filenames in os.walk(dirpath):
            # 去掉目标跟路径，只对目标文件夹下边的文件及文件夹进行压缩
            fpath = path.replace(dirpath, '')

            for filename in filenames:
                zip.write(os.path.join(path, filename), os.path.join(fpath, filename))
        zip.close()

#数据库操作
def newID():                                                         #给新任务用户分配ID（数据库内按递增顺序，ID为缺失的第一项，返回ID
    sel = "SELECT id FROM task"
    db = sqlite3.connect('data.db')
    cur = db.cursor()
    cur.execute(sel)
    db.commit()
    a=cur.fetchall()
    print(a)
    cur.close()
    db.close()
    if len(a) == 0:
        return 1
    c=[]
    for i in a:
        i=i[0]
        c.append(i)
    c.sort()
    flag = True
    for i in range(len(c)):
        if c[i]!=1 and flag == True:
            d=1
            flag = False
            break
        elif i!=0:
            if c[i-1]+1 != c[i]:
                flag = False
                d=c[i-1]+1
                break
        else:
            flag = False
            d=c[-1]+1
    return d
    
def sort2(a):                                         #冒泡排序
    for i in range(len(a)):
        for j in range(i, len(a)):
            if a[i] > a[j]:
                a[i], a[j] = a[j], a[i]
            if len(a)>=2:
                if a[-1] < a[-2]:
                    a[-1],a[-2]=a[-2],a[-1]
    return a

def creative(list1):                                                  #向数据库注入新任务（输入参数为列表，包含所有字段）
    ins = "INSERT INTO task VALUES(?,?,?,?,?,?)"
    id = list1[0]
    name = list1[1]
    old_path = list1[2]
    new_path = list1[3]
    retain_num = list1[4]
    status = list1[5]
    try:
        db = sqlite3.connect('data.db')
        cur = db.cursor()
        cur.execute(ins,(id,name,old_path,new_path,retain_num,status))
        db.commit()
        cur.close()
        db.close()
        return 1
    except:
        db.rollback ()
        return 0

def drop(b):                                                  #数据库任务删除
        try:
            db = sqlite3.connect('data.db')
            cur = db.cursor()
            cur.execute("DELETE FROM task where id = ? or name = ?",(b,b))
            db.commit()
            cur.close()
            db.close()
            return 1
        except:
            return 0

def select(b): 
        try:                                                       #数据查询(输入参数统一为用户名或ID，空值为查询所有)
            db = sqlite3.connect('data\data.db')
            cur = db.cursor()
            if b == "":
                sel = "SELECT * FROM task"
                cur.execute(sel)
            else:
                sel = "SELECT * FROM task where id == ? or name == ?"
                cur.execute(sel,(b,b))  
            db.commit()
            a=cur.fetchall()
            if len(a) > 1:
                a=sort2(a)
            cur.close()
            db.close()
            return a
        except:
            return 0

def change(a,i,b):                                                         #修改数据
        try:
            db = sqlite3.connect('data.db')
            cur = db.cursor()
            if i == 1:
                up = "UPDATE task SET name= ? where name == ? or id == ?"
                cur.execute(up,(a,b,b))
            elif i == 2:
                up = "UPDATE task SET old_path= ? where name == ? or id == ?"
                cur.execute(up,(a,b,b))
            elif i == 3:
                up = "UPDATE task SET new_path= ? where name == ? or id == ?"
                cur.execute(up,(a,b,b))
            elif i == 4:
                up = "UPDATE task SET retain_num= ? where name == ? or id == ?"
                cur.execute(up,(a,b,b))
            elif i == 5:
                if a == 'y':
                    a = '┗|｀O′|┛ 嗷~~'
                elif a == 'n':
                    a='-------------'
                up = "UPDATE task SET status= ? where name == ? or id == ?"
                cur.execute(up,(a,b,b))
            db.commit()
            cur.close()
            db.close()
            return 1
        except:
            return 0 

def off():                                                             #关闭，执行成功返回'1',执行失败返回'0'
        try:
            db = sqlite3.connect('data.db')
            cur = db.cursor()
            cur.execute("UPDATE task SET status='-------------'")
            db.commit()
            cur.close()
            db.close()
            return 1
        except:
            return 0

def on():                                                              #启动，执行成功返回'1',执行失败返回'0'
        try:
            db = sqlite3.connect('data.db')
            cur = db.cursor()
            cur.execute("UPDATE task SET status='┗|｀O′|┛ 嗷~~'")
            db.commit()
            cur.close()
            db.close()
            return 1
        except:
            return 0
'''
#获取文件时间
def file_time(filename):
    t = os.path.getmtime(filename)
    return datetime.datetime.fromtimestamp(t)
'''
#执行自动备份
def such():#搜索数据库中已启动的文件
        db = sqlite3.connect('data.db')
        cur = db.cursor()
        cur.execute("SELECT * FROM task where status == '┗|｀O′|┛ 嗷~~'")
        db.commit()
        a = cur.fetchall()
        cur.close()
        db.close()
        sort2(a)
        return a

def run(a):#执行自动备份
        for i in range(len(a)):
            try:
                start = time()
                print(a[i][2],'-->',a[i][3]+'\\'+a[i][1]+'.zip')
                crezip(a[i][2],a[i][3]+'\\'+a[i][1]+'.zip')
                end = time()
                print('---------------------------------------------------------------------------------')
                print('已备份'+a[i][1]+'.zip,共耗时：%s Seconds'%(end-start))
                print('---------------------------------------------------------------------------------')
            except:
                print('---------------------------------------------------------------------------------')
                print('本次{a[i][1]}.zip备份失败，已自动跳过本次备份')
                print('---------------------------------------------------------------------------------')            

def dele(a):#删除多余备份文件
    
        for i in range(len(a)):
            d=[]
            e=[]
            c=0
            b = os.listdir(a[i][3])
            for j in b:
                if a[i][1] in j:
                    c+=1
                    d.append(j)
                    e.append(j)
            for r in range(c):
                if c > a[i][4]:
                    for g in range(len(d)):
                        d[g]=d[g][-23:-5]
                    d.sort()
                    for x in range(len(b)):
                        if d[0] in e[x]:
                            try:
                                os.remove(a[i][3]+'\\'+e[x])
                                c-=1
                                print('---------------------------------------------------------------------------------')
                                print('已删除：',e[x])
                                print('---------------------------------------------------------------------------------')
                                del d[0]
                                break
                            except:
                                c-=1
                                del d[0]
                                print('---------------------------------------------------------------------------------')
                                print(e[x],'删除失败，已删除本次备份。。')
                                print('---------------------------------------------------------------------------------')
                                break
                else:
                    break

#启动自动备份程序线程
class run2(Thread):
    def run(self):
        i =0
        ti = 10
        while True:
            i+=1
            sleep(0.2)
            print('---------------------------------------------------------------------------------')
            print('已执行%d次'%i)
            print('---------------------------------------------------------------------------------')
            try:
                a= such()
                if len(a) != 0:
                    run(a)
                    dele(a)
                    sleep(ti)
                else:
                    print('无备份任务')
                    sleep(ti)
            except:
                sleep(ti)
    
#关闭主副程序
class exit1(Thread):
    def exited(self):
        pid = os.getpid()
        exit1.kill(pid)
    
    def kill(pid):#杀死进程
        if os.name == 'nt':
        # Windows下命令
            cmd = 'taskkill /pid ' + str(pid) + ' /f'
            try:
                os.system(cmd)
                print(pid, '已成功killed')
            except Exception as e:
                print(e)
        elif os.name == 'posix':
            # Linux下命令
            cmd = 'kill ' + str(pid)
            try:
                os.system(cmd)
                print(pid, 'killed')
            except Exception as e:
                print(e)
        else:
            print('Undefined os.name')



if __name__ == "__main__":                                                       #主程序，主控交互程序
    print('--------------------------正在启动后台自动备份任务。。。----------------------------')
    try:
        run1 = run2()
        run1.start()
        print('-------------------------------------启动成功！-------------------------------------')
    except:

        print('-------------------------启动失败！-------------------------')
    sleep(1)
    while True:
        try:
            while True:
                a = input('[1]创建任务\n[2]查询任务\n[3]编辑任务\n[4]删除任务\n[5]手动备份\n[6]先按下【Ctrl+C】再按【6】回车结束所有线程\n请输入：')                         #获取输入
                if a in '[1]创建任务\n[2]查询任务\n[3]编辑任务\n[4]删除任务\n[5]手动备份\n[6]先按下【Ctrl+C】再按【6】回车结束所有线程\n':
                    break
                else:
                    print('超出范围')
                    continue
            if a == '1' or a == '创建任务':                                                               #创建任务代码块
                print('请按顺序输入以下内容：')
                flag = True
                while flag == True:
                    newname = input('请输入用户名：')
                    try:
                        newID1 = newID()
                        print('用户ID已分配，ID为',newID1)
                        flag = False
                    except:
                        print('用户ID分配发生异常，请检查数据库连接后重试')
                        print('----------------------------------------------------------------------------------------')

                old_path = input("备份源路径（绝对路径）：")
                new_path = input('备份目标路径（绝对路径）：')
                retain_num = input('备份保留数量（默认为2份，建议2~5）：')
                if retain_num == '':
                    retain_num = 2
                elif int(retain_num) > 5:
                    print("           警告！！！！！！！！这样会造成大量的磁盘占用，回车继续，输入任意量重新填入      ┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m")
                    a = input()
                    if a != '':
                        continue
                status = input('是否立即启动任务，默认开启（Y/N）：').lower()
                if status == 'y' or status == '':
                    status = '┗|｀O′|┛ 嗷~~'
                elif status == 'n':
                    status = '-------------'
                else:
                    print('超出范围')
                    continue

                list1 = [newID1,newname,old_path,new_path,retain_num,status]
                t = creative(list1)
                if t == 1:
                    print("---------------------------------------创建结果------------------------------------------")
                    print('创建成功')
                    print('----------------------------------------------------------------------------------------')
                elif t == 0:
                    print("---------------------------------------创建结果------------------------------------------")
                    print('创建失败,请重试')
                    print('----------------------------------------------------------------------------------------')
            

            elif a == '2' or a == '查询任务':                                             #数据查询
                b = input('输入单一任务用户名或ID查询（直接回车查询所有）:')
                a=select(b)
                if a == 0:
                    print("---------------------------------------查询结果------------------------------------------")
                    print('查询失败')
                    print("----------------------------------------------------------------------------------------")
                elif a == []:
                    print("---------------------------------------查询结果------------------------------------------")
                    print('查询结果为空')
                    print("----------------------------------------------------------------------------------------")
                else:
                    print("---------------------------------------查询结果------------------------------------------")
                    for i in a:
                        print(i)
                    print("----------------------------------------------------------------------------------------")

            elif a == '3' or a == '编辑任务':                                            #任务编辑模块
                while True:
                    b = input('[1]单一修改\n[2]批量修改状态\n请输入：')
                    if b in '[1]单一修改\n[2]批量修改状态\n':
                        break
                    else:
                        print('超出范围')
                        continue
                if b == '1' or b == '单一修改':
                    b = input('输入用户名或ID：')
                    print('--------------------------------------------------------------------------------------------')
                    f = select(b)
                    if f==[]:
                        print('找不到该任务！')
                        print('--------------------------------------------------------------------------------------------')
                        continue
                        
                    elif len(f)>1:
                        r = ['key:'+str(i)+str(f[i-1]) for i in range(1,len(f)+1)]
                        
                        for i in r:
                            print(i)
                        print('--------------------------------------------------------------------------------------------')
                        print('查询到多个任务，请选择其一（输入key序号）')
                        g = int(input('请选择：'))
                        if g > len(f):
                            print('输入量超出范围')
                            print('------------------------------------------------------------------------------------------------------')
                            continue
                        b = r[g-1][6]
                        print('已选择',r[g-1])
                        print('--------------------------------------------------------------------------------------------')
                    else:
                        print('查询到此任务',f)
                        print('--------------------------------------------------------------------------------------------')
                    while True:
                        c = input('选择需要修改的项目(输入0放弃修改）：\n[1]用户名\n[2]备份源路径\n[3]备份目标路径\n[4]备份保留数目\n[5]任务状态\n请选择：')
                        if c in '[1]用户名\n[2]备份源路径\n[3]备份目标路径\n[4]备份保留数目\n[5]任务状态1213141523242534354512312412513413514523423524534512341235134512345':
                            break
                        else:
                            print('超出范围')
                            continue
                    c = [int(i) for i in c]
                    if 0 in c:
                        continue                  
                    for i in c:            #单个用户逐项修改
                        if i == 1:                                #修改用户名
                            newname = input('请输入新用户名：')
                            t = change(newname,i,b)
                            if t == 1:
                                print('已修改')
                                print('----------------------------------------------------------------------------------------')
                            elif t == 0:
                                print('修改失败，检查数据库连接')
                        elif i == 2:                                      #修改备份源路径
                            old_path = input("新备份源路径：")

                            t=change(old_path,i,b)
                            if t == 1:
                                print('已修改')
                                print('----------------------------------------------------------------------------------------')
                            elif t == 0:
                                print('修改失败，检查数据库连接')
                        elif i == 3:                                     #修改备份目标路径
                            new_path = input('新备份目标路径：')
                            t=change(new_path,i,b)
                            if t == 1:
                               print('已修改')
                               print('----------------------------------------------------------------------------------------')
                            elif t == 0:
                                print('修改失败，检查数据库连接')


                        elif i == 4:                                                         #修改备份保留数量
                            while True:
                                retain_num = input('新备份保留数量（默认为2份，建议2~5）：')
                                if retain_num <= '5':
                                    break
                                elif retain_num >'5':
                                    print("           警告！！！！！！！！这样会造成大量的磁盘占用，回车继续，输入任意量重新填入               ┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m┏┛墓┗┓...(((m -__-)m")
                                    h = input()
                                    if h == '':
                                        break
                                    else:
                                        continue
                            t=change(retain_num,i,b)
                            if t == 1:
                                print('已修改')
                                print('----------------------------------------------------------------------------------------')
                            elif t == 0:
                                print('修改失败，检查数据库连接')
                                print('----------------------------------------------------------------------------------------')
                        elif i == 5:                                                        #修改状态
                            status = input('是否立即启动任务（Y/N）：').lower()
                            t=change(status,i,b)
                            if t == 1:
                                print('已修改')
                                print('----------------------------------------------------------------------------------------')
                            elif t == 0:
                                print('修改失败，检查数据库连接')
                                print('----------------------------------------------------------------------------------------')
                    print('修改已完成')
                    print('--------------------------------------------------------------------------------------------')
                elif b == '2' or b == "批量修改状态" :
                    b = input('输入多个用户名或ID（用英文","隔开,直接回车为全选）：')
                    if b == '':
                        while True:
                            d = input('[1]全部启动[2]全部关闭\n请输入：')
                            if d in '[1]全部启动[2]全部关闭':
                                break
                            else:
                                print('超出范围')
                                continue
                        if d == '1':
                            a=on()
                            if a==1:
                                print('全部启动成功')
                                print('----------------------------------------------------------------------------------------')
                            else:
                                print('全部启动失败')
                                print('----------------------------------------------------------------------------------------')
                        elif d == '2':
                            a=off()
                            if a==1:
                                print('全部关闭成功')
                                print('----------------------------------------------------------------------------------------')
                            else:
                                print('全部关闭失败')
                                print('----------------------------------------------------------------------------------------')
                        continue

                    b = b.split(',')
                    for i in range(len(b)):
                        if b[i].isdigit()==True:
                            b[i]=int(b[i])
                        else:
                            continue
                    c = []
                    
                    for i in b:
                        a = select(i)
                        if a!=0:
                            c.append(a)
                        else:
                            continue
                    if c==[]:
                        print('查询内容为空')
                    else:
                        print('查询到以下内容：')
                    for i in c:
                        print(i)
                    print('------------------------------------------------------------------------------------------------------')
                    while True:
                        d = input('[1]全部启动[2]全部关闭\n请输入：')
                        if d in '[1]全部启动[2]全部关闭':
                            break
                        else:
                            print('超出范围')
                            continue
                    if d == '1':
                        a=on()
                        if a==1:
                            print('全部启动成功')
                            print('----------------------------------------------------------------------------------------')
                        else:
                            print('全部启动失败')
                            print('----------------------------------------------------------------------------------------')
                    elif d == '2':
                        a=off()
                        if a==1:
                            print('全部关闭成功')
                            print('----------------------------------------------------------------------------------------')
                        else:
                            print('全部关闭失败')
                            print('----------------------------------------------------------------------------------------')
            

            elif a == '4' or a == '删除任务':
                b = input('请输入需要删除的任务用户名或ID：')
                a = drop(b)
                if a == 1:
                    print('删除成功')
                    print('----------------------------------------------------------------------------------------')
                else:
                    print('删除失败')
                    print('----------------------------------------------------------------------------------------')

            
            elif a == '5' or a == '手动备份':
                input_path = input('请输入源路径+文件夹名称：')
                output_path = input('请输入目标路径：')
                input_path = PureWindowsPath(input_path)
                input_path = input_path.as_posix()
                output_path = PureWindowsPath(output_path)
                output_path = output_path.as_posix()
                a = os.listdir(output_path)
                b=1
                for i in range(len(a)):
                    if '手动备份' in a[i]:
                        b+=1
                output_path1 = output_path + '/手动备份%d.zip'%b
                
                try:
                    exec.crezip(input_path, output_path1)
                    print('备份成功,已备份到%s'%output_path)
                    print('文件名为：手动备份%d.zip'%b)
                    print('------------------------------------------------------------------------------------------------------')
                    continue
                except:
                    print('备份失败')
                    print('------------------------------------------------------------------------------------------------------')
                    continue


            elif a == '6' or a == '关闭所有程序':
                exit1.exited()
            
        except:
            print('\n------------------------------------------------------------------------------------')
            print('\nmanege.py程序出错，请检查....')
            print('\n')
